package com.znyj.servlet.utilsTool;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.net.*;
import java.util.Enumeration;
import java.util.regex.Pattern;

/**
 * Created by gaoliwei02 on 17/7/5.
 */
public class Helper {
    public static final String DEFAULT_URL_REGEX = "^/.*\\.(css|js|ico|gif|dmp|png|jpg|ttf)$";
    public static final int FAIL = 10002;
    public static final int DEFAULT_HTTP_PORT = 80;

    private static final Logger logger = LoggerFactory.getLogger(Helper.class);
    private static final String UNKNOWN = "unknownHost";
    private static Pattern pattern;

    static {
        // init first
        String ip = getLocalIp();
        pattern = Pattern.compile(Helper.DEFAULT_URL_REGEX);

    }

    public static boolean matchExclude(String action) {
        return pattern.matcher(action).matches();
    }

    public static String getField(HttpServletRequest request, String key) {
        String value = request.getHeader(key);
        if (isBlank(value)) {
            // TODO 存疑：不直接通过request.getParameter(key)读取参数，可能导致应用读取不到？
            // value = request.getParameter(key);
            value = getQueryParameter(request.getQueryString(), key);
            if (isBlank(value)) {
                value = getCookieValue(request, key);
            }
        }
        return value;
    }

    private static String getQueryParameter(String queryString, String key) {
        if (isBlank(queryString)) {
            return null;
        }
        String[] pairs = queryString.split("&");
        for (String pair : pairs) {
            if (!isBlank(pair) && pair.startsWith(key)) {
                String[] array = pair.split("=");
                return array.length == 2 ? array[1] : null;
            }
        }
        return null;
    }

    public static Cookie getCookie(HttpServletRequest request, String cookieName) {
        Cookie cookies[] = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(cookieName)) {
                    return cookie;
                }
            }
        }
        return null;
    }

    public static String getCookieValue(HttpServletRequest request, String cookieName) {
        Cookie cookie = getCookie(request, cookieName);
        return cookie == null ? null : cookie.getValue().trim();
    }

    private static String getRealIp(HttpServletRequest request) {
        String ip = head(request, "X-Real-IP");
        if (ip != null && !UNKNOWN.equalsIgnoreCase(ip)) {
            return ip;
        }
        ip = head(request, "X-Forwarded-For");
        if (ip != null) {
            int index = ip.indexOf(',');
            // 多次反向代理后会有多个IP值，第一个为真实IP。
            return (index >= 0) ? ip.substring(0, index) : ip;
        }
        ip = request.getHeader("Proxy-Client-IP");
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip == null ? "unkown" : ip;
    }

    private static String head(HttpServletRequest req, String s) {
        return req.getHeader(s);
    }

    public static String getLocalHostName() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
            return "unknown";
        }
    }

    public static String getLocalIp() {
        Enumeration<NetworkInterface> networkInterface;
        try {
            networkInterface = NetworkInterface.getNetworkInterfaces();
            while (networkInterface.hasMoreElements()) {
                NetworkInterface ni = networkInterface.nextElement();
                Enumeration<InetAddress> inetAddress = ni.getInetAddresses();
                while (inetAddress.hasMoreElements()) {
                    InetAddress ia = inetAddress.nextElement();
                    if (ia instanceof Inet6Address)
                        continue; // ignore ipv6
                    String thisIp = ia.getHostAddress();
                    if (thisIp != null && !ia.isLoopbackAddress() && !thisIp.contains(":") && !thisIp.startsWith("127.0.")) {
                        return thisIp;
                    }
                }
            }
        } catch (SocketException e) {
            logger.warn("can't getLocalIp", e);
        }
        return "127.0.0.1";
    }

    /**
     * 内网ip
     * 10.0.0.0~10.255.255.255
     * 192.168.0.0~192.168.255.255
     * 169.254.0.0~169.254.255.255
     * 172.16.0.0~172.31.255.255  性能考虑，先忽略这个网段
     *
     * @param ip
     * @return
     */
    private static boolean isIntranetIpv4(String ip) {
        if (ip.startsWith("10.") || ip.startsWith("192.168.") || ip.startsWith("169.254.")) {
            return true;
        }
        return false;
    }

    private static int intOr(String key, int defaultValue) {
        String value = string(key);
        try {
            return isBlank(value) ? defaultValue : Integer.valueOf(value);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    private static String string(String key) {
        return System.getProperty(key, "");
    }

    private static String string(String key, String defaultValue) {
        return System.getProperty(key, defaultValue);
    }

    public static boolean isBlank(CharSequence cs) {
        int strLen;
        if (cs == null || (strLen = cs.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(cs.charAt(i))) {
                return false;
            }
        }
        return true;
    }
}
